package cn.stylefeng.roses.ent.saas.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.ent.saas.entity.Tenant;
import cn.stylefeng.roses.ent.saas.enums.TenantExceptionEnum;
import cn.stylefeng.roses.ent.saas.factory.TenantFactory;
import cn.stylefeng.roses.ent.saas.factory.TenantLinkFactory;
import cn.stylefeng.roses.ent.saas.mapper.TenantMapper;
import cn.stylefeng.roses.ent.saas.pojo.dto.MenuAndOptionsDTO;
import cn.stylefeng.roses.ent.saas.pojo.request.TenantRequest;
import cn.stylefeng.roses.ent.saas.service.TenantService;
import cn.stylefeng.roses.kernel.auth.api.TenantCodeGetApi;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.db.mp.tenant.holder.TenantIdHolder;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.sys.api.expander.TenantConfigExpander;
import cn.stylefeng.roses.kernel.sys.modular.org.entity.HrOrganization;
import cn.stylefeng.roses.kernel.sys.modular.org.service.HrOrganizationService;
import cn.stylefeng.roses.kernel.sys.modular.position.entity.HrPosition;
import cn.stylefeng.roses.kernel.sys.modular.position.service.HrPositionService;
import cn.stylefeng.roses.kernel.sys.modular.role.entity.SysRole;
import cn.stylefeng.roses.kernel.sys.modular.role.service.SysRoleLimitService;
import cn.stylefeng.roses.kernel.sys.modular.role.service.SysRoleMenuOptionsService;
import cn.stylefeng.roses.kernel.sys.modular.role.service.SysRoleMenuService;
import cn.stylefeng.roses.kernel.sys.modular.role.service.SysRoleService;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUser;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUserOrg;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUserRole;
import cn.stylefeng.roses.kernel.sys.modular.user.service.SysUserOrgService;
import cn.stylefeng.roses.kernel.sys.modular.user.service.SysUserRoleService;
import cn.stylefeng.roses.kernel.sys.modular.user.service.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 租户信息业务实现层
 *
 * @author fengshuonan
 * @date 2023/08/30 17:04
 */
@Service
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements TenantService, TenantCodeGetApi {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private HrOrganizationService hrOrganizationService;

    @Resource
    private HrPositionService hrPositionService;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysUserOrgService sysUserOrgService;

    @Resource
    private SysRoleMenuService sysRoleMenuService;

    @Resource
    private SysRoleMenuOptionsService sysRoleMenuOptionsService;

    @Resource
    private SysRoleLimitService roleLimitService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(TenantRequest tenantRequest) {
        Tenant tenant = new Tenant();
        BeanUtil.copyProperties(tenantRequest, tenant);

        // 保存租户信息
        this.save(tenant);

        try {
            // 设定租户id为新生成的租户id
            TenantIdHolder.set(tenant.getTenantId());

            // 初始化租户
            this.initTenant(tenant, tenantRequest);

        } finally {
            // 移除tenantId临时缓存
            TenantIdHolder.remove();
        }
    }

    @Override
    public void del(TenantRequest tenantRequest) {
        Tenant tenant = this.queryTenant(tenantRequest);
        this.removeById(tenant.getTenantId());

        // 发布租户删除事件  todo

    }

    @Override
    public void edit(TenantRequest tenantRequest) {

        // 不能修改租户编码
        tenantRequest.setTenantCode(null);

        Tenant tenant = this.queryTenant(tenantRequest);
        BeanUtil.copyProperties(tenantRequest, tenant);
        this.updateById(tenant);
    }

    @Override
    public Tenant detail(TenantRequest tenantRequest) {

        Tenant tenant = this.queryTenant(tenantRequest);

        // 携带租户的统计信息
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<SysUser>().eq(SysUser::getTenantId, tenant.getTenantId());
        Long userCount = sysUserService.count(queryWrapper);
        tenant.setTenantUserCount(userCount);

        // 鞋带租户的组织机构统计信息
        LambdaQueryWrapper<HrOrganization> organizationLambdaQueryWrapper = new LambdaQueryWrapper<HrOrganization>().eq(
                HrOrganization::getTenantId, tenant.getTenantId());
        long orgCount = hrOrganizationService.count(organizationLambdaQueryWrapper);
        tenant.setTenantOrgCount(orgCount);

        return tenant;
    }

    @Override
    public PageResult<Tenant> findPage(TenantRequest tenantRequest) {
        LambdaQueryWrapper<Tenant> wrapper = createWrapper(tenantRequest);

        // 只查询列表需要的字段
        wrapper.select(Tenant::getTenantId, Tenant::getTenantName, Tenant::getTenantCode, Tenant::getTenantLogo, Tenant::getCompanyName,
                Tenant::getEmail, Tenant::getSafePhone, Tenant::getStatusFlag, Tenant::getActiveDate, Tenant::getExpireDate);

        Page<Tenant> sysRolePage = this.page(PageFactory.defaultPage(), wrapper);
        return PageResultFactory.createPageResult(sysRolePage);
    }

    @Override
    public boolean checkTenantCodeAlreadyExisted(TenantRequest tenantRequest) {
        LambdaQueryWrapper<Tenant> tenantLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tenantLambdaQueryWrapper.eq(Tenant::getTenantCode, tenantRequest.getTenantCode());

        if (ObjectUtil.isNotEmpty(tenantRequest.getTenantId())) {
            tenantLambdaQueryWrapper.ne(Tenant::getTenantId, tenantRequest.getTenantId());
        }

        return this.count(tenantLambdaQueryWrapper) > 0;
    }

    @Override
    public void initTenant(Tenant tenantInfo, TenantRequest tenantRequest) {

        // 初始化租户的管理员用户
        SysUser tenantAdminUser = TenantFactory.createTenantAdminUser(tenantRequest);

        // 初始化租户的总公司
        HrOrganization tenantHrOrganization = TenantFactory.createTenantHrOrganization(tenantRequest);

        // 初始化租户的默认职务
        HrPosition tenantPosition = TenantFactory.createTenantPosition();

        // 设置用户关联公司信息
        SysUserOrg sysUserOrg = TenantLinkFactory.createUserOrgLink(tenantAdminUser, tenantHrOrganization, tenantPosition);

        // 初始化租户的角色
        SysRole tenantRole = TenantFactory.createTenantRole(tenantRequest);

        // 创建用户和角色的关联信息
        SysUserRole userRoleLink = TenantLinkFactory.createUserRoleLink(tenantAdminUser, tenantRole);

        // 初始化租户默认的菜单和权限
        MenuAndOptionsDTO tenantMenuAndOptions = TenantLinkFactory.getTenantMenuAndOptions(tenantRole.getRoleId());

        // 进行保存操作
        this.sysUserService.save(tenantAdminUser);
        this.hrOrganizationService.save(tenantHrOrganization);
        this.hrPositionService.save(tenantPosition);
        this.sysUserOrgService.save(sysUserOrg);

        this.sysRoleService.save(tenantRole);
        this.sysUserRoleService.save(userRoleLink);

        if (ObjectUtil.isNotEmpty(tenantMenuAndOptions.getSysRoleMenuList())) {
            this.sysRoleMenuService.saveBatch(tenantMenuAndOptions.getSysRoleMenuList());
        }
        if (ObjectUtil.isNotEmpty(tenantMenuAndOptions.getSysRoleMenuOptionsList())) {
            this.sysRoleMenuOptionsService.saveBatch(tenantMenuAndOptions.getSysRoleMenuOptionsList());
        }
        if (ObjectUtil.isNotEmpty(tenantMenuAndOptions.getRoleLimitList())) {
            this.roleLimitService.saveBatch(tenantMenuAndOptions.getRoleLimitList());
        }
    }

    @Override
    public List<Tenant> findList(TenantRequest tenantRequest) {
        LambdaQueryWrapper<Tenant> wrapper = this.createWrapper(tenantRequest);

        // 只查询编码和名称
        wrapper.select(Tenant::getTenantCode, Tenant::getTenantName);

        return this.list(wrapper);
    }

    @Override
    public Long getTenantIdByCode(String tenantCode) {

        // 如果租户编码为空，那么返回默认的租户id
        if (ObjectUtil.isEmpty(tenantCode)) {
            return TenantConfigExpander.getDefaultRootTenantId();
        }

        // 查询租户id
        LambdaQueryWrapper<Tenant> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Tenant::getTenantCode, tenantCode);
        queryWrapper.select(Tenant::getTenantId);
        Tenant tenant = this.getOne(queryWrapper);

        if (tenant != null) {
            return tenant.getTenantId();
        }

        throw new ServiceException(TenantExceptionEnum.TENANT_EXISTED);
    }

    /**
     * 获取信息
     *
     * @author fengshuonan
     * @date 2023/08/30 17:04
     */
    private Tenant queryTenant(TenantRequest tenantRequest) {
        Tenant tenant = this.getById(tenantRequest.getTenantId());
        if (ObjectUtil.isEmpty(tenant)) {
            throw new ServiceException(TenantExceptionEnum.TENANT_NOT_EXISTED);
        }
        return tenant;
    }

    /**
     * 创建查询wrapper
     *
     * @author fengshuonan
     * @date 2023/08/30 17:04
     */
    private LambdaQueryWrapper<Tenant> createWrapper(TenantRequest tenantRequest) {
        LambdaQueryWrapper<Tenant> queryWrapper = new LambdaQueryWrapper<>();

        // 根据租户编码，租户名称，公司名称模糊查询
        String searchText = tenantRequest.getSearchText();
        if (ObjectUtil.isNotEmpty(searchText)) {
            queryWrapper.like(Tenant::getTenantCode, searchText);
            queryWrapper.or().like(Tenant::getTenantName, searchText);
            queryWrapper.or().like(Tenant::getCompanyName, searchText);
        }

        return queryWrapper;
    }

}